home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-2.iso / os2 / rsynth1.zip / say.c < prev    next >
Text File  |  1995-12-20  |  10KB  |  460 lines

  1. #include <config.h>
  2. /* $Id: say.c,v 1.13 1994/11/08 13:30:50 a904209 Exp a904209 $
  3.    $Log: say.c,v $
  4.  * Revision 1.13  1994/11/08  13:30:50  a904209
  5.  * 2.0 release
  6.  *
  7.  * Revision 1.12  1994/11/04  13:32:31  a904209
  8.  * 1.99.1 - Change configure stuff
  9.  *
  10.  * Revision 1.11  1994/11/02  10:55:31  a904209
  11.  * Add autoconf. Tested on SunOS/Solaris
  12.  *
  13.  * Revision 1.10  1994/10/04  17:12:50  a904209
  14.  * 3rd pre-release
  15.  *
  16.  * Revision 1.9  1994/10/04  09:08:27  a904209
  17.  * Next Patch merge
  18.  *
  19.  * Revision 1.8  1994/10/03  08:41:47  a904209
  20.  * 2nd pre-release                                                         
  21.  *
  22.  * Revision 1.7  1994/09/19  15:48:29  a904209
  23.  * Split hplay.c, gdbm dictionary, start of f0 contour, netaudio and HP ports
  24.  *
  25.  * Revision 1.6  1994/04/15  16:47:37  a904209
  26.  * Edits for Solaris2.3 (aka SunOs 5.3)
  27.  *
  28.  * Revision 1.5  1994/02/24  15:03:05  a904209
  29.  * Added contributed linux, NeXT and SGI ports.
  30.  *
  31.  * Revision 1.4  93/11/18  16:29:06  a904209
  32.  * Migrated nsyth.c towards Jon's scheme - merge still incomplete
  33.  * 
  34.  * Revision 1.3  93/11/16  14:32:44  a904209
  35.  * Added RCS Ids, partial merge of Jon's new klatt/parwave
  36.  *
  37.  * Revision 1.3  93/11/16  14:00:58  a904209
  38.  * Add IDs and merge Jon's klatt sources - incomplete
  39.  *
  40.  */
  41. char *say_id = "$Id: say.c,v 1.13 1994/11/08 13:30:50 a904209 Exp a904209 $";
  42. extern char *Revision;
  43. #include <stdio.h>
  44. #include <ctype.h>
  45. #include <useconfig.h>
  46. #include <math.h>
  47. #include "proto.h"
  48. #include "nsynth.h"
  49. #include "hplay.h"
  50. #include "dict.h"
  51. #include "ASCII.h"
  52. #include "darray.h"
  53. #include "holmes.h"
  54. #include "phtoelm.h"
  55. #include "text.h"
  56. #include "getargs.h"
  57. #include "phones.h"
  58. #include "file.h"
  59. #include "say.h"
  60.  
  61. char *program = "say";
  62.  
  63. static int verbose = 0;
  64.  
  65.  
  66. unsigned
  67. spell_out(word, n, phone)
  68. char *word;
  69. int n;
  70. darray_ptr phone;
  71. {
  72.  unsigned nph = 0;
  73. /* fprintf(stderr, "Spelling '%.*s'\n", n, word); */
  74.  while (n-- > 0)
  75.   {
  76.    nph += xlate_string(ASCII[*word++ & 0x7F], phone);
  77.   }
  78.  return nph;
  79. }
  80.  
  81. int
  82. suspect_word(s, n)
  83. char *s;
  84. int n;
  85. {
  86.  int i = 0;
  87.  int seen_lower = 0;
  88.  int seen_upper = 0;
  89.  int seen_vowel = 0;
  90.  int last = 0;
  91.  for (i = 0; i < n; i++)
  92.   {
  93.    char ch = *s++;
  94.    if (i && last != '-' && isupper(ch))
  95.     seen_upper = 1;
  96.    if (islower(ch))
  97.     {
  98.      seen_lower = 1;
  99.      ch = toupper(ch);
  100.     }
  101.    if (ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U' || ch == 'Y')
  102.     seen_vowel = 1;
  103.    last = ch;
  104.   }
  105.  return !seen_vowel || (seen_upper && seen_lower) || !seen_lower;
  106. }
  107.  
  108. static unsigned xlate_word PROTO((char *word, int n, darray_ptr phone));
  109.  
  110. static unsigned
  111. xlate_word(word, n, phone)
  112. char *word;
  113. int n;
  114. darray_ptr phone;
  115. {
  116.  unsigned nph = 0;
  117.  if (*word != '[')
  118.   {
  119.    if (dict)
  120.     {
  121.      unsigned char *p = dict_find(word, n);
  122.      if (p)
  123.       {
  124.        unsigned char *s = p;
  125.        while (*s)
  126.         {
  127.          char *x = dialect[(unsigned) (*s++)];
  128.          while (*x)
  129.           {
  130.            phone_append(phone, *x++);
  131.            nph++;
  132.           }
  133.         }
  134.        phone_append(phone, ' ');
  135.        free(p);
  136.        return nph + 1;
  137.       }
  138.      else
  139.       {
  140.        /* If supposed word contains '.' or '-' try breaking it up... */
  141.        char *h = word;
  142.        while (h < word + n)
  143.         {
  144.          if (*h == '.' || *h == '-')
  145.           {
  146.            nph += xlate_word(word, h++ - word, phone);
  147.            nph += xlate_word(h, word + n - h, phone);
  148.            return nph;
  149.           }
  150.          else
  151.           h++;
  152.         }
  153.       }
  154.     }
  155.    if (suspect_word(word, n))
  156.     {
  157.       nph = spell_out(word, n, phone);
  158.       return(nph);
  159.     }
  160.    else
  161.     {
  162.      if (dict || verbose)
  163.       /* fprintf(stderr, "Guess %p '%.*s'\n", dict, n, word) */; 
  164.      nph += NRL(word, n, phone);
  165.     }
  166.   }
  167.  else
  168.   {
  169.    if ((++word)[(--n) - 1] == ']')
  170.     n--;
  171.    while (n-- > 0)
  172.     {
  173.      phone_append(phone, *word++);
  174.      nph++;
  175.     }
  176.   }
  177.  phone_append(phone, ' ');
  178.  return nph + 1;
  179. }
  180.  
  181. void
  182. say_phones(phone, len, verbose)
  183. char *phone;
  184. int len;
  185. int verbose;
  186. {
  187.  darray_t elm;
  188.  unsigned frames;
  189.  darray_init(&elm, sizeof(char), len);
  190.  if ((frames = phone_to_elm(phone, len, &elm)))
  191.   {
  192.    unsigned max_samples = frames * klatt_global.nspfr;
  193.    short *samp = (short *) malloc(sizeof(short) * max_samples);
  194.    if (verbose)
  195.     fprintf(stderr,"%.*s\n", len, phone);
  196.    if (samp)
  197.     {
  198.      unsigned nsamp;
  199.  
  200.      nsamp = holmes(elm.items, (unsigned char *) darray_find(&elm, 0),
  201.                              max_samples, samp);
  202.      audio_play(nsamp, samp);
  203.      if (file_write)
  204.       (*file_write)(nsamp, samp);
  205.      free(samp);
  206.     }
  207.   }
  208.  darray_free(&elm);
  209. }
  210.  
  211.  
  212.  
  213.  
  214. unsigned
  215. xlate_string(string, phone)
  216. char *string;
  217. darray_ptr phone;
  218. {
  219.  unsigned nph = 0;
  220.  char *s = string;
  221.  char ch;
  222.  while (isspace(ch = *s))
  223.   s++;
  224.  while ((ch = *s))
  225.   {
  226.    char *word = s;
  227.    if (isalpha(ch))
  228.     {
  229.      while (isalpha(ch = *s) || ((ch == '\'' || ch == '-' || ch == '.') && isalpha(s[1])))
  230.       s++;
  231.      if (!ch || isspace(ch) || ispunct(ch) || (isdigit(ch) && !suspect_word(word, s - word)))
  232.       {
  233.       nph += xlate_word(word, s - word, phone);
  234.       }
  235.      else
  236.       {
  237.        while ((ch = *s) && !isspace(ch) && !ispunct(ch))
  238.         s++;
  239.        nph += spell_out(word, s - word, phone);
  240.       }
  241.     }
  242.    else if (isdigit(ch) || (ch == '-' && isdigit(s[1])))
  243.     {
  244.      int sign = (ch == '-') ? -1 : 1;
  245.      long value = 0;
  246.      if (sign < 0)
  247.       ch = *++s;
  248.      while (isdigit(ch = *s))
  249.       {
  250.        value = value * 10 + ch - '0';
  251.        s++;
  252.       }
  253.      if (ch == '.' && isdigit(s[1]))
  254.       {
  255.        word = ++s;
  256.        nph += xlate_cardinal(value * sign, phone);
  257.        nph += xlate_string("point", phone);
  258.        while (isdigit(ch = *s))
  259.         s++;
  260.        nph += spell_out(word, s - word, phone);
  261.       }
  262.      else
  263.       {
  264.        /* check for ordinals, date, time etc. can go in here */
  265.        nph += xlate_cardinal(value * sign, phone);
  266.       }
  267.     }
  268.    else if (ch == '[' && strchr(s, ']'))
  269.     {
  270.      char *word = s;
  271.      while (*s && *s++ != ']')
  272.       /* nothing */ ;
  273.      nph += xlate_word(word, s - word, phone);
  274.     }
  275.    else if (ispunct(ch))
  276.     {
  277.      switch (ch)
  278.       {
  279.         /* On end of sentence flush the buffer ... */
  280.        case '!':
  281.        case '?':
  282.        case '.':
  283.         if ((!s[1] || isspace(s[1])) && phone->items)
  284.          {
  285.           say_phones((char *) darray_find(phone, 0), phone->items, verbose);
  286.           phone->items = 0;
  287.          }
  288.         s++;
  289.         phone_append(phone, ' ');
  290.         break;
  291.        case '"':                 /* change pitch ? */
  292.        case ':':
  293.        case '-':
  294.        case ';':
  295.        case ',':
  296.        case '(':
  297.        case ')':
  298.         s++;
  299.         phone_append(phone, ' ');
  300.         break;
  301.        case '[':
  302.         {
  303.          char *e = strchr(s, ']');
  304.          if (e)
  305.           {
  306.            s++;
  307.            while (s < e)
  308.             phone_append(phone, *s++);
  309.            s = e + 1;
  310.            break;
  311.           }
  312.         }
  313.        default:
  314.         nph += spell_out(word, 1, phone);
  315.         s++;
  316.         break;
  317.       }
  318.     }
  319.    else
  320.     {
  321.      while ((ch = *s) && !isspace(ch))
  322.       s++;
  323.      nph += spell_out(word, s - word, phone);
  324.     }
  325.    while (isspace(ch = *s))
  326.     s++;
  327.   }
  328.  return nph;
  329. }
  330.  
  331. char *
  332. concat_args(argc, argv)
  333. int argc;
  334. char *argv[];
  335. {
  336.  int len = 0;
  337.  int i;
  338.  char *buf;
  339.  for (i = 1; i < argc; i++)
  340.   len += strlen(argv[i]) + 1;
  341.  buf = (char *) malloc(len);
  342.  if (buf)
  343.   {
  344.    char *d = buf;
  345.    for (i = 1; i < argc;)
  346.     {
  347.      char *s = argv[i++];
  348.      while (*s)
  349.       *d++ = *s++;
  350.      if (i < argc)
  351.       *d++ = ' ';
  352.      else
  353.       *d = '\0';
  354.     }
  355.   }
  356.  return buf;
  357. }
  358.  
  359. void
  360. say_string(s)
  361. char *s;
  362. {
  363.  darray_t phone;
  364.  darray_init(&phone, sizeof(char), 128);
  365.  xlate_string(s, &phone);
  366.  if (phone.items)
  367.   say_phones((char *) darray_find(&phone, 0), phone.items, verbose);
  368.  darray_free(&phone);
  369. }
  370.  
  371. extern int darray_fget PROTO((FILE * f, darray_ptr p));
  372.  
  373. int
  374. darray_fget(f, p)
  375. FILE *f;
  376. darray_ptr p;
  377. {
  378.  int ch;
  379.  while ((ch = fgetc(f)) != EOF)
  380.   {
  381.    phone_append(p, ch);
  382.    if (ch == '\n')
  383.     break;
  384.   }
  385.  phone_append(p, '\0');
  386.  return p->items - 1;
  387. }
  388.  
  389. extern void say_file PROTO((FILE * f));
  390.  
  391. void
  392. say_file(f)
  393. FILE *f;
  394. {
  395.  darray_t line;
  396.  darray_t phone;
  397.  darray_init(&line, sizeof(char), 128);
  398.  darray_init(&phone, sizeof(char), 128);
  399.  while (darray_fget(f, &line))
  400.   {
  401.    xlate_string((char *) darray_find(&line, 0), &phone);
  402.    line.items = 0;
  403.   }
  404.  if (phone.items)
  405.   say_phones((char *) darray_find(&phone, 0), phone.items, verbose);
  406.  darray_free(&phone);
  407.  darray_free(&line);
  408. }
  409.  
  410. int main PROTO((int argc, char *argv[]));
  411.  
  412. int
  413. main(argc, argv)
  414. int argc;
  415. char *argv[];
  416. /* char *env[]; */       
  417. {
  418. /* program = argv[0]; */
  419.  
  420.  
  421.  _control87(  RC_UP       | EM_UNDERFLOW | EM_INVALID  | 
  422.             EM_ZERODIVIDE | EM_DENORMAL  | EM_OVERFLOW | 
  423.             EM_INEXACT ,    MCW_EM | MCW_RC);
  424.  
  425.  argc = audio_init(argc, argv);
  426.  argc = init_synth(argc, argv);
  427.  argc = init_holmes(argc, argv);
  428.  argc = dict_init(argc, argv);
  429.  argc = file_init(argc, argv);
  430.  argc = getargs("Misc",argc, argv, "v", NULL, &verbose, "Verbose, show phonetic form",NULL);
  431.  
  432.  if (help_only)
  433.   {
  434.    fprintf(stderr,"Usage: %s [options as above] words to say\n",program);
  435.    fprintf(stderr,"or     %s [options as above] < file-to-say\n",program);
  436.    fprintf(stderr,"(%s)\n",Revision);
  437.   }
  438.  else
  439.   {
  440.    if (argc > 1)    
  441.     {               
  442.      char *s = concat_args(argc, argv);
  443.      if (s)         
  444.       {             
  445.        say_string(s);
  446.        free(s);     
  447.       }             
  448.     }               
  449.    else             
  450.     say_file(stdin);
  451.   }
  452.  if (file_term)
  453.   (*file_term)();
  454.  audio_term();
  455.  term_holmes();
  456.  if (dict)
  457.   dict_term();
  458.  return (0);
  459. }
  460.